<?

class mysqlDriver extends ObjectClass{

	//----------------------------------------------//
	// VERIFICATION									//
	//----------------------------------------------//

	//Fonction associee a Check qui verifie les donnees entre sql et le schema
	//Si elle n'existe pas on la cree, et si la creation ne marche pas on renvoie une erreur
	function initData () {
		//require_once("Class/");
		mysqlCheck::initData();
	}

	function createData () {
		//require_once("Class/");
		mysqlCheck::createData();
	}


	//----------------------------------------------//
	// RECHERCHE					//
	//----------------------------------------------//

	//Effectue une recherche et la renvoie a lanalyse
	function DriverSearch($Analyse,$Select,$GroupBy){
		$Data = mysqlFunctions::joinSql($Analyse,$Data);
		$sql  = mysqlFunctions::createSql("SELECT",$Data,$Select);
		$Results=$this->executeSql($sql,"SELECT",$GroupBy);
		return (sizeof($Results)!=0) ? $this->analyzeSearch($Results,"",1) : false;
	}

	/* Cette fonction range et classe dans un tableau les donnees trouvees.
	 Renvoi: le tableau de resultat.
	 Parametres: les donnees trouvees dans la base de donnees, la recherche effectuee*/
	function analyzeSearch($Donnees, $Recherche) {
		$Resultat= Array(); $compteur=0;
		//On procede au calcul de la note que l'on enregistre, avec le reste, dans le tableau final
		if (is_array($Resultat))foreach ($Donnees as $Enregistrement){
			if (!is_array($Enregistrement)) continue;
			$sOrder = $totalCibles+1;
			$Resultat[$compteur] = $Enregistrement;
			$Resultat[$compteur]['ObjectType'] = $this->titre;
			$Resultat[$compteur]['note'] = 10;
			$compteur++;
		}
		return $Resultat;
	}



	//----------------------------------------------//
	// INSERTION					//
	//----------------------------------------------//
	//Insere un nouvel objet ou met a jour un ancien selon la presence de lid
	function insertObject($Properties,$Update=0){
		if ($Properties['Id']==NULL) {
			foreach ($Properties as $NomProp=>$ValeurProp){
				if($Flag) {$Noms.=",";$Valeurs.=",";$RefWhere.=" AND ";}
				$Noms.= '`'.$NomProp.'`';
				$Valeurs.= '\''.addslashes($ValeurProp).'\'';
				if ($NomProp!="Id")$RefWhere .= '(`'.$NomProp.'` = \''.addslashes($ValeurProp).'\' )';
				$Flag=true;
			}
			//On construit la requete SQL
			$sql = 'INSERT INTO `'.$this->Prefix.$this->titre.'` ('.$Noms.') VALUES ('.$Valeurs.')';
			//GESTION DES INTERVALLES
			if ($this->isReflexive()==1){
				//Alors il faut mettre l index intervallaire a jour
				$Parent = $Properties[$this->findReflexive()];
			}
		}else{
			foreach ($Properties as $NomProp=>$ValeurProp){
				if ($Update=="1") {
					if($Flag) $Requete.=" , ";
					$Requete.= "`$NomProp`='".addslashes($ValeurProp)."'";
				}else{
					if($Flag) {$Noms.=",";$Valeurs.=",";}
					$Noms.= '`'.$NomProp.'`';
					$Valeurs.= '\''.addslashes($ValeurProp).'\'';
				}
				$Flag=true;
			}
			//On construit la requete SQL
			if ($Update==1)$sql = 'UPDATE `'.$this->Prefix.$this->titre.'` SET '.$Requete.' WHERE `Id`='.$Properties['Id'];
			else $sql = 'REPLACE INTO `'.$this->Prefix.$this->titre.'` ('.$Noms.') VALUES ('.$Valeurs.')';
			//			echo $sql;
			//GESTION DES INTERVALLES
			if ($this->isReflexive()){
				//Alors il faut mettre l index intervallaire a jour
				$Parent = $Properties[$this->findReflexive()];
			}
		}
		$this->executeSql($sql,"UPDATE");
		//GESTION DES INTERVALLES
		if ($this->isReflexive()&&($this->findReflexiveCard()=="0,1"||$this->findReflexiveCard()=="1,1")) {
			//On recupere l id de l elemnt inserï¿œ
			$Id = $GLOBALS["Systeme"]->Db[$this->Bdd]->lastInsertID();
			//On ajoute l element a lindex intervallaire
			mysqlInterval::insertIntervalData($Id,$Parent);
		}
		return $Properties;
	}

	//----------------------------------------------//
	// MODFICATION					//
	//----------------------------------------------//
	//Modifie les droits
	function changeRights($Id,$Ui="",$Gi="",$Um="",$Gm="",$Om="")	{
		$sql = "UPDATE `".$this->Prefix.$this->titre."` SET ";
		$sql.="uid=$Ui,gid=$Gi,umod=$Um,omod=$Om,gmod=$Gm WHERE Id=$Id";
		$this->executeSql($sql,"UPDATE");
		return true;
	}

	//Ajoute ou met a jour une association
	function insertKey($Tab,$Id,$Type){
		$TabFields = $this->AddNeededFields('',"ASSOC");
		if (is_array($this->childOf)) foreach ($this->childOf as $Child) {
			if ($Child["Titre"]==$Tab["Titre"]) $C = $Child;
		}
		//Cas d'une clef reflexive
		if ($Tab['Titre']==$this->titre&&($C["Card"]=="0,n"||$C["Card"]=="1,n")) {
			if (!array_key_exists('Id',$Tab)) $Tab['Id'] = $Tab['NouvelId'];
			$sql = "INSERT INTO `".$this->Prefix.$C["Table"]."` SET ";
			foreach ($TabFields as $Nom=>$Valeur){
				if ($Nom!="tmsCreate"||$Nom!="userCreate") $sql.=$Nom."=".$Valeur.", ";
			}
			if ($Tab["Id"]!=""&&$ab["Id"]!=0) $sql.= "`".$C['Titre']."Id`=".$Tab['Id'].', ';
			else $sql.= "`".$C['Titre']."Id`=NULL, ";
			$sql.="`".$C["Champ"]."`=".$Id;
			return $this->executeSql($sql,"UPDATE");
		}
		$Card = $this->findKey($Tab['Fkey'],'parent','Card');
		if (!$Card) return false;
		//Cas d'une clef secondaire longue
		if (in_array($Card,$this->isLongKey)){
			if (array_key_exists("AncienId",$Tab)){
				//C'est une modif
				$NumAssoc = substr($Tab['numAssoc'],1,strlen($Tab['numAssoc']));
				$sql = "UPDATE `".$this->Prefix.$Tab['Table']."` SET ";
				foreach ($TabFields as $Nom=>$Valeur){
					if ($Nom!="tmsCreate"||$Nom!="userCreate") $sql.=$Nom."=".$Valeur.", ";
				}
				$sql.= $Tab['Fkey']."Id=".$Tab['Id'].', ';
				$sql.= $this->titre."=".$Id;
				$sql.= ' WHERE Id='.$NumAssoc;
			}else{
				$sql = "SELECT * FROM `".$this->Prefix.$C["Table"]."` WHERE `".$this->titre."`=$Id AND ";
				if ($Tab["Id"]!="")$sql.= "`".$Tab['Titre']."Id`=".$Tab['Id'];
				else $sql.="`".$Tab['Fkey']."Id` IS NULL";
				$result = $this->executeSql($sql,"SELECT_SYS");
				if (sizeof($result)) return false;
				if (!array_key_exists('Id',$Tab)) $Tab['Id'] = $Tab['Id'];
				//C'est une insertion
				$sql =  "INSERT INTO `".$this->Prefix.$C['Table']."`  SET ";
				$TabFields = $this->AddNeededFields('','ASSOC');
				foreach ($TabFields as $Nom=>$Valeur){
					if ($Nom!="tmsCreate"||$Nom!="userCreate") $sql.=$Nom."=".$Valeur.", ";
				}
				if ($Tab["Id"]!=""&&$Tab["Id"]!=0) $sql.= "`".$C['Titre']."Id`=".$Tab['Id'].', ';
				else $sql.= "`".$C['Titre']."Id`=NULL, ";
				$sql.= "`".$this->titre."`=".$Id;
			}
		}
		if (in_array($Card,$this->isShortKey)){
			$sql = "UPDATE `".$this->Prefix.$this->titre."` SET ";
			foreach ($TabFields as $Nom=>$Valeur){
				if ($Nom!="tmsCreate"||$Nom!="userCreate") $sql.=$Nom."=".$Valeur.", ";
			}
			$NomChamp = $this->findKey($Tab['Titre'],'parent');
			if ($Tab['Id']!=""&&$Tab['Id']!=0) $sql.=$NomChamp."=".$Tab['Id'];
			else $sql.=$NomChamp." = NULL";
			$sql.= ' WHERE Id='.$Id;
		}
		return $this->executeSql($sql,"UPDATE");
	}

	//----------------------------------------------//
	// UTILITAIRES					//
	//----------------------------------------------//
	//Selon le type de la propriete et la langue en vigueur il ajoute le prefixe de langue ou pas
	function langProp($Name) {
		// 		print_r($this->Proprietes);
		//print_r($this->Proprietes[$Name]);
		//echo "$Name $Special \r\n";
		if (array_key_exists($Name,$this->Proprietes)){
			$Special = $this->Proprietes[$Name]["special"];
		}
		$Prefixe = $GLOBALS["Systeme"]->Language[$GLOBALS["Systeme"]->DefaultLanguage];
		$isNotDefault = $GLOBALS["Systeme"]->DefaultLanguage!=$GLOBALS["Systeme"]->LangageDefaut;
		//echo "$isNotDefault\r\n";
		if ($isNotDefault && !$GLOBALS["Systeme"]->User->Admin && $Special=="multi") $Name= "".$Prefixe."-".$Name;
		//echo $GLOBALS["Systeme"]->User->Admin." $Special $Prefixe - $Name\r\n";
		return $Name;
	}



	//----------------------------------------------//
	// SUPPRESSION					//
	//----------------------------------------------//
	//Detruit un objet et toutes les associations qu-il comprend
	function DriverErase($Id){
		$sql="DELETE FROM `".$this->Prefix.$this->titre."` WHERE Id=\"".$Id."\"";
		$Flag = $this->executeSql($sql,"DELETE");
		if (is_array($this->childOf)) foreach($this->childOf as $Assoc){
			$Flag=$this->EraseTableAssociation($Id,"c",$Assoc);
		}
		if (is_array($this->parentOf)) foreach($this->parentOf as $Assoc) {
			$Flag=$this->EraseTableAssociation($Id,"p",$Assoc);
		}
		if ($this->isReflexive()&&($this->findReflexiveCard()=="0,1"||$this->findReflexiveCard()=="1,1")){
			$this->removeIntervalData($Id);
		}
		return $Flag;
	}

	//Detruit toutes les associations vers Id dans la tqble
	function EraseTableAssociation($Id,$Type,$Assoc){
		//Pour les card n1, seul les parents sont concernes
		$sql="";
		if (in_array($Assoc['Card'],$this->isShortKey) && $Type=="p"){
			if ($this->titre==$Assoc['Titre']) $sql="UPDATE `".$this->Prefix.$this->titre."` SET `".$Assoc['Champ']."`='' WHERE `".$Assoc['Champ']."`=\"".$Id."\"";
			else $sql="UPDATE `".$this->Prefix.$Assoc['Titre']."` SET `".$Assoc['Champ']."`='' WHERE `".$Assoc['Champ']."`=\"".$Id."\"";
		}
		if (in_array($Assoc['Card'],$this->isLongKey)){
			if ($Type=="c"){
				$sql="DELETE FROM `".$this->Prefix.$Assoc['Table']."` WHERE `".$this->titre."`=\"".$Id."\"";
			}
			elseif ($Type=="p"){
				$sql="DELETE FROM `".$this->Prefix.$Assoc['Table']."` WHERE `".$Assoc['Champ']."`=\"".$Id."\"";
			}
		}
		if ($sql!="") return $this->executeSql($sql,"DELETE");
		else return true;
	}


	//Supprime une association
	function EraseAssociation($currentId,$beforeDs,$beforeId){
		foreach($this->childOf as $Parent){
			if ($Parent['Titre']==$beforeDs) $Relative = $Parent;
		}
		//On efface l'association de this vers X ou X vers this dans une table
		if (in_array($Relative['Card'],$this->isShortKey) && $this->titre==$beforeDs){
			$ChampRef=$this->findReflexive();
			$sql="UPDATE `".$this->Prefix.$this->titre."` SET `".$ChampRef."`='' WHERE (`Id`=\"".$currentId."\")";
		}
		if (in_array($Relative['Card'],$this->isShortKey) && $this->titre!=$Relative['Titre']){
			$ChampKey=$this->findKey($Relative['Titre'],'parent');
			$sql="UPDATE `".$this->Prefix.$this->titre."` SET `".$ChampKey."`='' WHERE (`Id`=".$currentId.")";
		}
		if (in_array($Relative['Card'],$this->isLongKey)){
			$sql="DELETE FROM `".$this->Prefix.$Relative['Table']."` WHERE ";
			if ($beforeId!=""&&$beforeId!=0){
				$sql.=" (`".$Relative['Titre']."Id`=".$beforeId.")";
			}else{
				$sql.="((`".$Relative['Champ']."`=0) OR (`".$Relative['Champ']."` IS NULL))";
			}
			$sql.= "AND (`".$this->titre."`=".$currentId.")";
		}
		if ($sql!="") return $this->executeSql($sql,"UPDATE_SYS");
		else return true;
	}

	//----------------------------------------------//
	// EXPORTATION					//
	//----------------------------------------------//

	//Exporation d'une table complete dans un fichier
	function fillTable() {
		//On verifie qu il esxiste un fichier
		$Path = "Modules/".$this->Module."/Backup/".$this->titre.".sql";
		if (file_exists($Path)) {
			//Alors on insere les donnÃ©es ligne apres ligne
			$file = fopen($Path,"r");
			while (!feof($file)){
				$ligne=fgets($file,4096);
				$sql="INSERT INTO `".$this->Prefix.$this->titre."` ".$ligne;
				mysqlDriver::executeSql($sql,"INSERT");
			}
		} else $GLOBALS['Systeme']->Log->log("/ERREUR Impossible de trouver le jeu d essai ".$this->titre);
		return true;
	}
	//Exporation d'une table complete dans un fichier
	function saveData(){
		$sql="SELECT * FROM `".$this->Prefix.$this->titre."` as m";
		if (!$resql=$this->executeSql($sql,"SELECT")) return false;
		@mkdir("Modules/".$this->Module."/Backup/");
		$Path="Modules/".$this->Module."/Backup/".$this->titre.".sql";
		$Fichier=fopen($Path,'w');
		$GLOBALS['Systeme']->Log->log("/INFO Enregistrement du fichier  ".$this->titre);
		foreach ($resql as $Selection){
			foreach ($Selection as $Nom=>$Valeur){
				if ($this->isProperties($Nom) || $this->isFKey($Nom )||$Nom=="uid"||$Nom=="gid"||$Nom=="umod"||$Nom=="gmod"||$Nom=="omod") {
					if ($Flag){ $Noms.=','; $Valeurs.=",";}
					$Noms.='`'.$Nom.'`';
					$Valeurs.='"'.htmlentities($Valeur).'"';
					$Flag=true;
				}else{

				}
			}
			$ligne="(".$Noms.") VALUES (".$Valeurs.")\r\n";
			fwrite($Fichier,$ligne);
			$Noms = $Valeurs = $Flag = "";
		}
		return (file_exists($Path)) ? true:false;
	}

	//Renvoie l'ensemble des donnï¿œes propre ï¿œ un group
	function saveGroupData($gId){
		$sql = "select * from `".$this->Prefix.$this->titre."` ";
		$sql .= "where (gId=$gId) OR (omod>1)";
		$requete = mysql_query($sql) or die(mysql_error());
		while ($Resultat = mysql_fetch_assoc($requete)){
			$this->ObjectTable[] = $Resultat;
			$sql = "INSERT INTO `%LEPREFIXE%-".$this->Module."-".$this->titre."` (";
			foreach ($Resultat as $Nom=>$Valeur){
				if ($Flag) {$Noms.=", ";$Valeurs.=", ";}
				$Noms .= '`'.$Nom.'`';
				$Valeurs .= '"'.addslashes($Valeur).'"';
				if (!$Flag) $Flag = true;
			}
			$sql .= $Noms.") VALUES ($Valeurs);";
			$TabSql[] = $sql;
			$Noms = $Valeurs = $Flag = "";
		}
		if (is_array($this->childOf)) foreach ($this->childOf as $Parent){
			if ($Parent["Card"]=="0,n"||$Parent["Card"]=="1,n"){
				$sql = "select * from `".$this->Prefix.$this->titre.$Parent["Titre"]."` ";
				$requete = mysql_query($sql) or die(mysql_error());
				while ($Resultat = mysql_fetch_assoc($requete)){
					//On verifie que l'id appartient bien au User
					$Verif =$GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$Parent["Id"]]->idPossess($Resultat[$Parent["Titre"]."Id"]);
					if ($this->idPossess($Resultat[$this->titre]) && $Verif){
						$sql = "INSERT INTO `%LEPREFIXE%-".$this->Module."-".$this->titre.$Parent["Titre"]."` VALUES ('".$Resultat["Id"]."','".$Resultat["tmsCreate"]."','".$Resultat["userCreate"]."','".$Resultat["tmsEdit"]."','".$Resultat["userEdit"]."','".$Resultat[$this->titre]."','".$Resultat[$Parent["Titre"]."Id"]."');";
						$TabSql[] = $sql;
					}
				}
			}
		}
		return $TabSql;
	}



	//----------------------------------------------//
	// EXECUTION SQL				//
	//----------------------------------------------//
	//Execution d une requete SQL
	function executeSql($sql,$type='SELECT',$GroupBy=""){
		$GLOBALS["Systeme"]->connectSQL();
		//if ($this->titre=="Article") file_put_contents("requete.log",$sql);
		//----------------------------------------------//
		//Gestion des limites et des orders 		//
		//----------------------------------------------//
		$Tab = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->LimRequete;
		$Order = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->Order;
		//----------------------------------------------//
		//#TODO test existance champs order 		//
		//Su oui alors on ordonne sur ce champ egalement//
		//Si non c par Id par defaut			//
		//----------------------------------------------//
		if ($GroupBy!="") $sql.= ' GROUP BY '.$GroupBy;
		if ($type=="SELECT" && strlen($Order[0]) && strlen($Order[1])) {
			$sql.= ' ORDER BY '.((preg_match("#\(#",$Order[0]))?'m.':'').$Order[0].' '.$Order[1];
		}elseif ($type=="SELECT") {
			//Par defaut on doit ranger par le champ de type order
			$Champs = $this->getSpecialProp("order");
			if (is_array($Champs)) {
				$sql.= ' ORDER BY ';
				foreach ($Champs as $Nom=>$Prop) {
					$sql.= 'm.'.$Nom;
					if ($i) $sql.=",";
					$i=true;
				}
				$sql.= ' ASC,m.Id DESC';
			}
		}
		if ($type=="SELECT"&&strlen($Tab[0])&&strlen($Tab[1])) $sql.= ' LIMIT '.$Tab[0].','.$Tab[1];
		if ($type=="SELECT" || $type="SYS_SELECT") $Result = $GLOBALS["Systeme"]->Db[$this->Bdd]->queryAll ( $sql );
		else {
			$Result = $GLOBALS["Systeme"]->Db[$this->Bdd]->exec ( $sql );
			//$Result = mysql_fetch_assoc($sql);
		}
/*		echo "--------------------------------\r\n";
		echo $sql."\r\n";*/
		//$GLOBALS["Systeme"]->Log->log("DEBUG",$sql);
		if (MDB2::isError($Result)){
// 			echo "<div class='Error'>ERREURS SQL : $sql\r\n</div><br />";
			return false;
		}
		return $Result;
	}
}
